#!/usr/bin/env python
# -*- coding: utf-8 -*-

'''
充值handle模块
'''

from lib.myweb import WebApplication
from lib.validate import Filter
from lib.validate import Check

from common import auth
from common.myconfig import CONF
from common.myvalidate import ValidatorCommon
from common.mydata import ModelCharge


class FilterCharge(Filter):
    '充值模块专用过滤器'
    @staticmethod
    def get_signature(target_list, key):
        '根据密钥和内容生成签名'
        import hashlib
        import urllib

        content = urllib.urlencode(target_list) + key
        sign = hashlib.sha1(content).hexdigest()

        return sign


class ValidatorCharge(ValidatorCommon):
    '充值模块专用校验器'
    @staticmethod
    @Check.is_len_range(1, 8)
    @Check.is_digit(True)
    def check_amount(target_str):
        '检查数额'
        return True

    @staticmethod
    @Check.is_len_range(32)
    @Check.is_alnum(False)
    def check_service_sn(target_str):
        '检查商家SN号'
        return True

    @staticmethod
    @Check.is_len_range(32)
    @Check.is_alnum(False)
    def check_pay_sn(target_str):
        '检查支付订单SN号'
        return True

    @staticmethod
    @Check.is_len_range(10)
    @Check.is_digit(False)
    def check_client_sn(target_str):
        '检查客户SN号'
        return True


class HandleCharge(WebApplication):
    '充值handle'
    _HANDLE_NAME = 'charge'  # handle名称，用于模板前缀
    _PATH_PREFIX = '/charge'  # 一级路径名称，用于解析path

    @auth.session(auth.SESSION_LEVEL['user'])
    def action_index(self):
        '充值提示页面'
        # 查找该用户所有未付款的订单信息
        user_id = self._session['user_info']['id']
        mod_chg = ModelCharge()
        charge_infos = mod_chg.select_by_unpaid(user_id)
        if not charge_infos:
            charge_infos = []

        self._render.view['charge_infos'] = charge_infos
        self._render.view['pay_user_url'] = CONF['pay_user_url']

    @auth.session(auth.SESSION_LEVEL['user'])
    @auth.token
    def action_order(self):
        '支付提示页面'
        import urllib
        import cgi
        from igor import urlfetch

        pay_create_url = CONF['pay_create_url']
        pay_user_url = CONF['pay_user_url']
        mod_chg = ModelCharge()

        # 检查订单信息
        form = self._request.form
        charge_info, error_type = ValidatorCharge.check_from_dict(
                form, ['amount', ])
        if error_type:
            return self.error_type(error_type)

        # 生成充值订单
        amount = charge_info['amount']
        user_id = self._session['user_info']['id']
        charge_info = mod_chg.create(user_id, amount)
        if not charge_info:
            return self.error_type('create_failed')

        # 请求支付接口获取支付订单号
        pay_dict = []
        pay_dict.append(('amount', amount))
        pay_dict.append(('service_sn', CONF['service_sn']))
        # 根据上面的内容生成签名
        sign = FilterCharge.get_signature(pay_dict, CONF['service_key'])
        pay_dict.append(('sign', sign))

        pay_data = urllib.urlencode(pay_dict)
        pay_header = {'Content-Type': 'application/x-www-form-urlencoded'}
        response = urlfetch.fetch(
                url=pay_create_url,
                payload=pay_data,
                method='POST',
                headers=pay_header)

        # 检查响应内容，一旦出错则移除充值订单
        res_content = response.content
        res_forms = cgi.parse_qs(res_content)
        res_form = {}
        for k in res_forms:
            res_form[k] = res_forms[k][0]

        if 'result' not in res_form:
            mod_chg.remove(charge_info['id'])
            return self.error_type('response_error')
        if res_form['result'] != 'ok':
            mod_chg.remove(charge_info['id'])
            return self.error_type(res_form['result'])

        check_list = ['pay_sn', 'sign']
        res_info, error_type = ValidatorCharge.check_from_dict(
                res_form, check_list)
        if error_type:
            mod_chg.remove(charge_info['id'])
            return self.error_type(error_type)

        # 检查签名
        content = []
        content.append(('result', res_form['result']))
        content.append(('pay_sn', res_info['pay_sn']))
        sign = FilterCharge.get_signature(content, CONF['service_key'])
        if sign != res_info['sign']:
            mod_chg.remove(charge_info['id'])
            return self.error_type('sign_error')

        # 更新订单信息（增加支付号）
        count = mod_chg.add_pay_sn(charge_info['id'], res_info['pay_sn'])
        if not count:
            mod_chg.remove(charge_info['id'])
            return self.error_type('add_sn_error')

        self._render.view['pay_sn'] = res_info['pay_sn']
        self._render.view['pay_user_url'] = pay_user_url

    @auth.session(auth.SESSION_LEVEL['user'])
    def action_confirm(self):
        '检查用户是否已完成支付'
        from igor import urlfetch
        import urllib
        import cgi

        pay_check_url = CONF['pay_check_url']
        mod_chg = ModelCharge()

        # 检查订单信息
        form = self._request.form
        charge_info, error_type = ValidatorCharge.check_from_dict(
                form, ['pay_sn', ])
        if error_type:
            return self.error_type(error_type)

        # 检查充值订单信息
        pay_sn = charge_info['pay_sn']
        charge_info = mod_chg.select_by_sn(pay_sn)
        if not charge_info:
            return self.error_type('pay_sn_error')

        # 请求支付接口检查支付订单号支付状态
        pay_dict = []
        pay_dict.append(('pay_sn', pay_sn))
        pay_dict.append(('service_sn', CONF['service_sn']))
        # 根据上面的内容生成签名
        sign = FilterCharge.get_signature(pay_dict, CONF['service_key'])
        pay_dict.append(('sign', sign))

        pay_data = urllib.urlencode(pay_dict)
        pay_header = {'Content-Type': 'application/x-www-form-urlencoded'}
        response = urlfetch.fetch(
                url=pay_check_url,
                payload=pay_data,
                method='POST',
                headers=pay_header)

        # 检查响应内容
        res_content = response.content
        res_forms = cgi.parse_qs(res_content)
        form_checked = {}
        for pay_status in ModelCharge.PAY_STATUS:
            form_checked[pay_status] = []
            pay_sn_list = res_forms.get(pay_status, [])
            for pay_sn in pay_sn_list:
                if ValidatorCharge.check(pay_sn, 'pay_sn'):
                    form_checked[pay_status].append(pay_sn)

        # 检查签名
        res_form = {'sign': res_forms.get('sign', [''])[0]}
        sign_info, error_type = ValidatorCharge.check_from_dict(
                res_form, ['sign', ])
        if error_type:
            return self.error_type(error_type)

        content = []
        for pay_status in ModelCharge.PAY_STATUS:
            for pay_sn in form_checked[pay_status]:
                content.append((pay_status, pay_sn))
        sign = FilterCharge.get_signature(content, CONF['service_key'])
        if sign != sign_info['sign']:
            mod_chg.remove(charge_info['id'])
            return self.error_type('sign_error')

        self._render.view['res'] = 'failed'
        # 取消充值订单
        pay_sn_list = form_checked['canceled']
        for pay_sn in pay_sn_list:
            mod_chg.update_canceled(pay_sn)

        # 修改充值订单为已付款
        pay_sn_list = form_checked['paid']
        for pay_sn in pay_sn_list:
            mod_chg.update_paid(pay_sn)
            self._render.view['res'] = 'success'


application = HandleCharge()
